#include "action.h"
#include <QVBoxLayout>
#include <QtXmlPatterns/QXmlQuery>
#include <QGroupBox>
#include <QLabel>
#include <QLineEdit>
#include "textedit.h"
#include "dateedit.h"
#include "treedoc.h"
#include "performerslist.h"
#include "approvedialog.h"
#include "disparition.h"
#include "confirmdialog.h"
#include "ordersdialog.h"
#include "reporteditdialog.h"

Action::Action(Protocol *parent): DocEntity(parent),m_expiry(QDate::currentDate())
{
    setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicator);
    DbConnection::QueryResult res = dynamic_cast<TreeDoc*>(treeWidget())
                                    ->execute("select * from =schema=.ex_operations where element_type=4");
    if(res.success())
    {
        for(int i=0;i<res.rows();i++)
        {
            QAction* action = new QAction(res.at(i,2).toString(),this);
            if(res.at(i,1).toInt()==8)
            {
                connect(action,SIGNAL(triggered()),this,SLOT(save()));
                action->setIcon(QIcon(":/save_entity"));
            }
            if(res.at(i,1).toInt()==12)
            {
                connect(action,SIGNAL(triggered()),this,SLOT(remove()));
                action->setIcon(QIcon(":/delete_entity"));
            }
            if((res.at(i,1).toInt()==13)||(res.at(i,1).toInt()==17))
            {
                connect(action,SIGNAL(triggered()),this,SLOT(approve()));
                if(res.at(i,1).toInt()==17) action->setText(tr("Согласовать мероприятие"));
                action->setIcon(QIcon(":/approve"));
            }
            if(res.at(i,1).toInt()==14)
            {
                action->setIcon(QIcon(":/approve"));
                action->setVisible(false);
            }
            if(res.at(i,1).toInt()==15)
            {
                action->setIcon(QIcon(":/approve"));
                connect(action,SIGNAL(triggered()),this,SLOT(approve()));
                action->setVisible(true);
            }
            if(res.at(i,1).toInt()==18)
            {
                connect(action,SIGNAL(triggered()),this,SLOT(finished()));
                action->setIcon(QIcon(":/check"));
            }
            if(res.at(i,1).toInt()==19)
            {
                connect(action,SIGNAL(triggered()),this,SLOT(newProtocol()));
                action->setIcon(QIcon(":/new_protocol"));
            }
            if(action!=0) operations()->addOperation(res.at(i,1).toInt(),action);
        }
        QAction* action = new QAction(QIcon(":/refresh"),tr("Обновить"),this);
        connect(action,SIGNAL(triggered()),this,SLOT(refresh()));
        operations()->addOperation(50,action);
        operations()->setEnabled(50,true);
        operations()->addOperation(100,new QAction(QIcon(":/add_user"),tr("Добавить ответственного"),this));
        operations()->addOperation(200,new QAction(QIcon(":/delete_user"),tr("Удалить ответственного"),this));
        operations()->addOperation(20,new QAction(QIcon(":/report_add"),tr("Новый отчет об эффективности"),this));
        operations()->addOperation(300,new QAction(QIcon(":/reports"),tr("Отчеты об эффективности"),this));
        operations()->setEnabled(300,true);
        //operations()->setEnabled(20,true);
    }
}

void Action::giveBithTo(){}
QWidget* Action::tabPage(QWidget *Parent, QTextEdit *content, DateEdit *date, QTextEdit *opinion)
{
    QWidget* page = new QWidget(Parent);
    QVBoxLayout* main = new QVBoxLayout;
    main->setAlignment(Qt::AlignTop);
    page->setLayout(main);
    if(content!=0)
    {
        main->addWidget(new QLabel(tr("Содержание"),page));
        main->addWidget(content);
    }
    if(date!=0)
    {
        QHBoxLayout* hlay = new QHBoxLayout;
        hlay->addWidget(new QLabel(tr("Срок исполнения"),page));
        hlay->addWidget(date);
        main->addLayout(hlay);
    }
    if(opinion!=0)
    {
        main->addWidget(new QLabel(tr("Особое мнение"),page));
        main->addWidget(opinion);
    }
    return page;
}

void Action::newProtocol()
{
    ConfirmDialog dialog(dynamic_cast<TreeDoc*>(treeWidget())->db(),treeWidget());
    dialog.exec();
    if(dialog.result()==QDialog::Rejected) return;
    Protocol *item = dynamic_cast<Protocol*>(parent());
    Disparition *disparition=dynamic_cast<Disparition*>(item->parent());
    DbConnection::QueryResult res = dynamic_cast<TreeDoc*>(treeWidget())->execute(tr("select =schema=.in_uid()"));
    if(res.success())
    {
        item = new Protocol(disparition,this);
        item->setID(0);
        item->setNum(disparition->childCount());
        item->setAuthor(dynamic_cast<TreeDoc*>(treeWidget())->users()->user(res.at(0,0).toInt()));
        emit childWakedUp(item);
    }
}
QString Action::capTemplate()
{
    return tr("Мероприятие");
}
QString Action::content() const
{
    return m_content;
}
QDate Action::expiry() const
{
    return m_expiry;
}
bool Action::removeFromDB()
{
    return dynamic_cast<TreeDoc*>(treeWidget())
                                    ->execute(tr("select =schema=.ex_delete_action(%1)").arg(id())).success();
}
void Action::setContent(const QString &Content)
{
    m_content=Content;
    emit changed();
}
void Action::setExpiry(const QDate &date)
{
    m_expiry=date;
    emit changed();
}
void Action::finished()
{
    ConfirmDialog dialog(dynamic_cast<TreeDoc*>(treeWidget())->db(),treeWidget());
    dialog.exec();
    if(dialog.result()==QDialog::Rejected) return;
    dynamic_cast<TreeDoc*>(treeWidget())->execute(tr("select =schema=.ex_confirmcomplet(%1)").arg(id()));
    refresh(Himself);
}
void Action::appendPerformer(const int &ID)
{
    m_performers.append(ID);
}

void Action::changePerformer(const int &view, const int &ID)
{
    m_performers[view]=ID;
    emit changed();
}
QWidget* Action::view(ViewTypes viewType)
{
    QWidget* widget = new QWidget(treeWidget());
    QVBoxLayout* main = new QVBoxLayout;
    main->setContentsMargins(0,0,0,0);
    QGroupBox* gbox = new QGroupBox(text(0),widget);
    QVBoxLayout* vlay = new QVBoxLayout;
    gbox->setLayout(vlay);
    //Панель с вкладками
    m_tab = new QTabWidget(widget);
    vlay->addWidget(m_tab);
    //Содержание мероприятия
    TextEdit* w_content = new TextEdit(widget);
    w_content->setReadOnly(!operations()->isEnabled(8));
    w_content->setText(m_content);
    connect(w_content,SIGNAL(textChanged(QString)),this,SLOT(setContent(QString)));
    //Срок исполнения мероприятия
    DateEdit* w_expiry = new DateEdit(widget);
    w_expiry->setDate(m_expiry);
    w_expiry->blockSignals(true);
    connect(w_expiry,SIGNAL(dateChanged(QDate)),this,SLOT(setExpiry(QDate)));
    w_expiry->setEnabled(operations()->isEnabled(8));
    w_expiry->blockSignals(false);
    //Добавление исходной вкладки
    m_tab->addTab(tabPage(widget,w_content,w_expiry,0),tr("Исходные данные"));
    //Добавление вкладок ответственных за исполнение
    foreach(int uid, m_info.keys())
    {
        w_content=0; w_expiry=0;
        TextEdit* w_opinion=0;
        bool addPage=false;
        if(m_info.value(uid).content!="")
        {
            w_content = new TextEdit(widget);
            w_content->setReadOnly(true);
            w_content->setText(m_info.value(uid).content);
            addPage=true;
        }
        if(m_info.value(uid).expiry!="")
        {
            w_expiry = new DateEdit(widget);
            w_expiry->setReadOnly(true);
            QVariant x(m_info.value(uid).expiry);
            w_expiry->setDate(x.toDate());
            addPage=true;
        }
        if(m_info.value(uid).opinion!="")
        {
            w_opinion = new TextEdit(widget);
            w_opinion->setReadOnly(true);
            w_opinion->setText(m_info.value(uid).opinion);
            addPage=true;
        }
        if(addPage)m_tab->addTab(tabPage(widget,w_content,w_expiry,w_opinion),
                               dynamic_cast<TreeDoc*>(treeWidget())->users()->user(uid)->name(User::FIO));
    }
    main->addWidget(gbox);
    //Список ответственных за исполнение
    PerformersList* list = new PerformersList(dynamic_cast<TreeDoc*>(treeWidget())->users(),widget);
    list->setEnabled(operations()->isEnabled(8));
    connect(list,SIGNAL(performerChange(int,int)),this,SLOT(changePerformer(int,int)));
    connect(operations()->operation(100),SIGNAL(triggered()),list,SLOT(appendPerformer()));
    connect(operations()->operation(200),SIGNAL(triggered()),list,SLOT(removePerformer()));
    connect(operations()->operation(300),SIGNAL(triggered()),this,SLOT(ordersView()));
    connect(operations()->operation(20),SIGNAL(triggered()),this,SLOT(appendOrder()));
    foreach(int id, m_performers)list->appendPerformer(id);
    connect(list,SIGNAL(sizeChange(int)),this,SLOT(performersCountChange(int)));
    if(m_performers.count()==0) list->appendPerformer();
    vlay->addWidget(list);
    QHBoxLayout* hlay = new QHBoxLayout;
    QVBoxLayout* l_vlay = new QVBoxLayout;
    QVBoxLayout* r_vlay = new QVBoxLayout;
    //Статус
    hlay->addLayout(l_vlay);
    hlay->addStretch();
    hlay->addLayout(r_vlay);
    vlay->addLayout(hlay);
    l_vlay->addWidget(new QLabel(tr("Статус"),widget));
    QLineEdit* w_status = new QLineEdit(widget);
    w_status->setText(status());
    w_status->setReadOnly(true);
    w_status->setEnabled(false);
    r_vlay->addWidget(w_status);
    widget->setLayout(main);
    return widget;
}
void Action::performersCountChange(const int &count)
{
    while(count!=m_performers.count())
    {
        if(count>m_performers.count())
            m_performers.append(0);
        else
            m_performers.takeAt(m_performers.count()-1);
    }
    operations()->operation(100)->setEnabled(true);
    operations()->operation(200)->setEnabled(true);
    if(count==1) operations()->operation(200)->setEnabled(false);
    if(count==4) operations()->operation(100)->setEnabled(false);
    emit changed();
}
bool Action::saveToDB()
{
    bool ok=isCorrect();
    if(!ok) return false;
    if(id()==0)
    {
        QStringList prfs;
        foreach(int ID,m_performers) prfs.append(tr("%1").arg(ID));
        QString sql="select =schema=.ex_append_action(%1,%2,'%3'::text,'%4'::timestamp,'{%5}'::int[])";
        sql=sql.arg(parent()->id())
               .arg(num())
               .arg(content())
               .arg(expiry().toString("yyyy-MM-dd"))
               .arg(prfs.join(","));
        DbConnection::QueryResult res = dynamic_cast<TreeDoc*>(treeWidget())->execute(sql);
        if(res.success())

            setID(res.at(0,0).toInt());
        else
            ok=false;
    }
    else
    {
        QStringList prfs;
        foreach(int ID,m_performers) prfs.append(tr("%1").arg(ID));
        QString sql="select =schema=.ex_change_action(%1,'%2'::text,'%3'::timestamp,'{%4}'::int[],%5)";
        sql=sql.arg(id())
               .arg(content())
               .arg(expiry().toString("yyyy-MM-dd"))
               .arg(prfs.join(","))
               .arg(num());
        DbConnection::QueryResult res = dynamic_cast<TreeDoc*>(treeWidget())->execute(sql);
        ok=res.success();
    }
    if(ok)setChanged(false);
    return ok;
}
bool Action::isCorrect()
{
    bool ok=false;
    QString tmp =content();
    tmp=tmp.replace(QRegExp("\\s"),"");
    ok=!tmp.isEmpty();
    return ok;
}
bool Action::isCompleted()
{
    return state()==480;
}
bool Action::isPerformed()
{
    return state()==470;
}
bool Action::isDelinquent()
{
    return state()==490;
}
bool Action::isEdited()
{
    return state()<470;
}
void Action::approve()
{
    bool ok=false;
    if(state()!=420)
    {
        ApproveDialog dialog(this,treeWidget());
        ok=dialog.exec()==QDialog::Accepted;
    }
    else
    {
        int uid=0;
        foreach(int key,m_info.keys())
            if(m_info.value(key).content!=""||m_info.value(key).expiry!="") uid=key;
        QMessageBox box(m_tab);
        box.setWindowTitle(tr("Согласование"));
        box.setText(tr("Принять изменения внесенные %1?")
                    .arg(dynamic_cast<TreeDoc*>(treeWidget())->users()->user(uid)->name(User::FIO)));
        QAbstractButton* yes=box.addButton(tr("Да"),QMessageBox::AcceptRole);
        box.addButton(tr("Нет"),QMessageBox::RejectRole);
        QAbstractButton* cancel=box.addButton(tr("Отмена"),QMessageBox::RejectRole);
        box.exec();
        QString val="false";
        if(box.clickedButton()==yes) val="true";
        if(box.clickedButton()==cancel) return;
        ConfirmDialog dialog(dynamic_cast<TreeDoc*>(treeWidget())->db(),&box);
        dialog.exec();
        if(dialog.result()==QDialog::Rejected) return;

        if(dynamic_cast<TreeDoc*>(treeWidget())->execute(tr("select =schema=.ex_agreement(%1,%2)").arg(id()).arg(val)).success())
        {
            ok=true;
            emit stateMessage(tr("Мероприятие согласовано"),5000);
        }
        else
            emit stateMessage(tr("Ошибка согласования"),5000);
    }
    if(ok)
    {
        refresh(Himself);
    }
}
void Action::refresh(const RefreshType &refreshType)
{

    DbConnection::QueryResult res=dynamic_cast<TreeDoc*>(treeWidget())->
                                  execute(tr("select * from =schema=.ex_actions where eid=%1").arg(id()));
    if(res.success()&&res.rows()>0)
    {
        blockSignals(true);
        setID(res.at(0,0).toInt());
        setNum(res.at(0,2).toInt());
        setContent(res.at(0,3).toString());
        QStringList prf = res.at(0,4).toString().replace(QRegExp("[{}]"),"").split(",");
        m_performers.clear();
        foreach(QString id, prf) appendPerformer(id.toInt());
        setExpiry(res.at(0,5).toDate());
        setState(res.at(0,6).toInt());
        setNote(res.at(0,7).toString());
        blockSignals(false);
        operations()->turnOff();
        operations()->setEnabled(50,true);
        QStringList ops = res.at(0,8).toString().replace(QRegExp("[{}]"),"").split(",",QString::SkipEmptyParts);
        if(ops.count()>0)
        foreach(QString id,ops)
        {
             operations()->setEnabled(id.toInt(),true);
             if(id.toInt()==8)
             {
                operations()->setEnabled(100,true);
                operations()->setEnabled(200,true);
             }
        }
        blockSignals(false);
        if(refreshType==Himself)
        {
            emit wasRefresh();
            emit childWakedUp(this);
        }
    }
}
void Action::setNote(const QString &note)
{
    QString buf=note,res;
    buf=buf.replace(QRegExp("[{}]"),"");
    QStringList xml = buf.split(",");
    QXmlQuery q;
    foreach(buf,xml)
    {
        buf=buf.replace("\\\"","'");
        buf=buf.replace(QRegExp("(^\"|\"$)"),"");
        q.setFocus(buf);
        q.setQuery("/performer/@uid/string()");
        if(q.evaluateTo(&res))
        {
            int uid=res.toInt();
            CEO ceo;
            //Поиск измененного содержания
            q.setQuery(tr("/performer[@uid='%1']/content/string()").arg(uid));
            if(q.evaluateTo(&res))
            {
                res.chop(1);
                ceo.content=res;
            }
            //Поиск измненного срока исполнения
            q.setQuery(tr("/performer[@uid='%1']/expiry/@date/string()").arg(uid));
            if(q.evaluateTo(&res))
            {
                res.chop(1);
                ceo.expiry=res;
            }
            //Поиск особого мнения
            q.setQuery(tr("/performer[@uid='%1']/opinion/string()").arg(uid));
            if(q.evaluateTo(&res))
            {
                res.chop(1);
                ceo.opinion=res;
            }
            m_info[uid]=ceo;
        }
    }
}

void Action::ordersView()
{
    OrdersDialog dialog(dynamic_cast<TreeDoc*>(treeWidget())->db(),
                        dynamic_cast<TreeDoc*>(treeWidget())->users(),
                        id(),
                        m_performers,
                        treeWidget());
    dialog.exec();
}

void Action::appendOrder()
{
    ReportEditDialog dialog(this,treeWidget());
    dialog.exec();
   /* if(dialog.exec()==QDialog::Accepted)
    {

    }*/
}
